#pragma once

#include <vector>
#include <deque>

const uint32 ENTITY_INDEX_BITS = 24;
const uint32 ENTITY_INDEX_MASK = (1 << ENTITY_INDEX_BITS) - 1;

const uint32 ENTITY_GENERATION_BITS = 8;
const uint32 ENTITY_GENERATION_MASK = (1 << ENTITY_GENERATION_BITS) - 1;

struct Entity
{
	uint32 id;

	Entity();
	Entity(const Entity& entity);
	Entity(const uint32 setId);
	inline bool operator==(const Entity& entity) { return id == entity.id; }
	inline bool operator!=(const Entity& entity) { return id != entity.id; }
	inline bool operator<(const Entity& entity) { return index() < entity.index(); }
	inline bool operator>(const Entity& entity) { return index() > entity.index(); }

	uint32 index() const { return id & ENTITY_INDEX_MASK; }
	uint32 generation() const { return (id >> ENTITY_INDEX_BITS) & ENTITY_GENERATION_MASK; }
};

class EntityManager
{
private:
	std::vector<unsigned char> _generation;
	std::deque<uint32> _free_indices;

public:
	EntityManager();
	~EntityManager();

	Entity Create();
	void Destroy(Entity e);
	bool Alive(Entity e) const;
};

struct Instance
{
	int32 i;

	Instance();
	Instance(const Instance& instance);
	Instance(const int32 newI);
};